package main

import (
	"flag"
	"fmt"
	//"html/template"
	"net/http"
	"os"
	"path/filepath"
	"strings"
	//"strconv"
)

type Page struct {
	Title      string
	Randseq    string
	Iterations string
	FalsePos   string
	File1      string
	File2      string
	//PACKAGENAME string
}

type ResultsPage struct {
	Title string
	Table string
}

type PATH struct {
	Name       string
	FalsePos   string
	Iterations string
	Randseq    string
	GOPATH     string
}

func Walkfunc(path string, info os.FileInfo, err error) error {
	if !info.IsDir() && strings.Contains(path, "ManipulationTests") && strings.Contains(path, "TestOutput.txt") {
		paths = append(paths, path)
	}
	return nil
}

func NewPATH(path, filename string) *PATH {

	s := new(PATH)
	(*s).Name = filename
	(*s).GOPATH = path + "/" + filename + "/diffresults"
	string1 := readFile((*s).GOPATH + "/TestOutput.txt")
	stringsplit := strings.Split(string1, "\n")
	cmd_args := strings.Split(stringsplit[len(stringsplit)-2], " ")
	if cmd_args[3] == "0" {
		(*s).Randseq = "Random"
	} else {
		(*s).Randseq = "Sequential"
	}
	(*s).Iterations = cmd_args[len(cmd_args)-1]
	(*s).FalsePos = stringsplit[len(stringsplit)-1]
	return s
}

var args = make([]string, 0)
var paths []string
var PACKAGENAME = ""
var RESULTS_DIR = ""
var DEBUG = ""
var GOSRC = os.Getenv("GOPATH") + "/src/"

func resultHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	PACKAGENAME = r.Form["PACKAGENAME"][0]
	RESULTS_DIR = GOSRC + PACKAGENAME + "/ManipulationTests"

	title := "Manipulation Results"
	table := ""
	text := resultText

	names, err := readDir(RESULTS_DIR)

	if err == nil {
		names = filterDirnames(names)

		PATHS := make([]*PATH, 0)

		for _, v := range names {
			PATHS = append(PATHS, NewPATH(RESULTS_DIR, v))
		}

		table = setupResultsTable(PATHS)
	} else {
		text += "No test results in directory"
	}

	if DEBUG == "1" {
		text += "DEBUG"
	}

	HTMLOut := fmt.Sprintf(text, title, table)
	fmt.Fprintf(w, "%s", HTMLOut)

}

func rootHandler(w http.ResponseWriter, r *http.Request) {

	paths = make([]string, 0)
	pathmap := make(map[string][]string)
	completepath := make(map[string][]string)

	err := filepath.Walk("/Users/schoonwi/Documents/GO/src", Walkfunc)
	if err != nil {
		fmt.Println("There was file/directory read problem")
	}

	for _, v := range paths {
		replaced := strings.Replace(v, "/", " ", 12)
		splits := strings.Split(replaced, " ")
		pathmap[splits[6]] = append(pathmap[splits[6]], splits[8])
		completepath[splits[6]] = append(completepath[splits[6]], v)
	}

	table := `<html>
    		<h1>ManipulationTests</h1>
    			`

	for key, paths := range pathmap {

		table += fmt.Sprintf(`<table border="1px" width = "600">
                <tr>
                <th width="400">%s</th><th><a href='/result?PACKAGENAME=%s'>View</a></th>
                </tr>`, key, key)
		for i, path := range paths {

			string1 := readFile(completepath[key][i])
			stringsplit := strings.Split(string1, "\n")
			cmd_args := strings.Split(stringsplit[len(stringsplit)-2], " ")

			table += fmt.Sprintf(`
						<tr>
		                <td align="center">%s</td>
		                <td>%s of %s</td>
		                 </tr>`, path, stringsplit[len(stringsplit)-1], cmd_args[len(cmd_args)-1])
		}
	}
	table += `</html>`

	fmt.Fprintf(w, "%s", table)

}

func compareHandler(w http.ResponseWriter, r *http.Request) {

	r.ParseForm()
	path := r.Form["GOPATH"][0]
	packagename := r.Form["PACKAGENAME"][0]
	currentfile := r.Form["CURRENTFILE"][0]

	thisPATH := NewPATH(RESULTS_DIR, currentfile)
	string0 := readFile((*thisPATH).GOPATH + "/TestOutput.txt")
	strsplit := strings.Split(string0, "\n")
	strsplit = strsplit[0 : len(strsplit)-2]

	var file1, file2 string

	for i, _ := range strsplit {
		if _, ok := r.Form[string(fmt.Sprintf("Compare%d", i))]; ok {
			file1 = path + "/" + packagename + ".go"
			file2 = path + "/" + packagename + fmt.Sprintf("_mani%d.go", i)
		}
	}

	table := `<table border="1px">

                <tr>
                    <th>Result</th>
                    <th>Compare</th>
                </tr>`

	for i, v := range strsplit {
		if strings.Contains(v, "INSUFFICIENT TESTS") {
			table += fmt.Sprintf(`
					<tr>
	                <td>%s</td>
	                <td><INPUT TYPE = "submit" Name = "Compare%d" 
	                    VALUE = "Compare%d">
	                </td></tr>`, v, i, i)
		} else if DEBUG == "1" {
			table += fmt.Sprintf(`
					<tr>
	                <td>%s</td>
	                <td><INPUT TYPE = "submit" Name = "Compare%d" 
	                    VALUE = "Compare%d">
	                </td></tr>`, v, i, i)
		}
	}

	table += `</table>`

	string1 := readFile(file1)
	string2 := readFile(file2)

	title := "Test Results"
	randseq := (*thisPATH).Randseq
	iters := fmt.Sprintf("Iterations: %s", (*thisPATH).Iterations)
	falsepos := fmt.Sprintf("All tests passed with manipulation : %s", (*thisPATH).FalsePos)

	HTMLOut := fmt.Sprintf(compareText, title, randseq, iters, falsepos, table, path, packagename, currentfile, string1, string2)
	fmt.Fprintf(w, "%s", HTMLOut)

}

func main() {

	flag.Parse()
	args = flag.Args()
	fetchResults(args)

	http.HandleFunc("/", rootHandler)
	http.HandleFunc("/result", resultHandler)
	http.HandleFunc("/compare", compareHandler)
	http.HandleFunc("/dojo.js", dojoHandler)
	http.HandleFunc("/diffview.js", diffviewHandler)
	http.HandleFunc("/difflib.js", difflibHandler)
	http.HandleFunc("/diffview.css", diffcssHandler)
	http.ListenAndServe(":8082", nil)
}

func readFile(file1 string) string {

	f1, err0 := os.Open(file1)
	if err0 != nil {
		//panic("File open error")
		//fmt.Println("There was a file error")
		return ""
	}
	stat1, _ := f1.Stat()

	fout1 := make([]byte, stat1.Size())
	_, err0 = f1.Read(fout1)

	if err0 != nil {
		panic("File read error")
	}

	string1 := fmt.Sprintf("%s", fout1)

	return string1

}

func readDir(filename string) ([]string, error) {

	f0, err := os.Open(filename)
	if err != nil {
		fmt.Println("No tests in directory")
		return make([]string, 0), err
	}
	dirStat, _ := f0.Stat()

	names, err := f0.Readdirnames(int(dirStat.Size()))

	return names, err
}

func filterDirnames(names []string) []string {

	filtered := make([]string, 0)
	for _, v := range names {
		if strings.Contains(v, PACKAGENAME) && strings.Contains(v, "_mani") {
			filtered = append(filtered, v)
		}
	}
	return filtered
}

func setupResultsTable(PATHS []*PATH) string {

	tableHTML := `<table border="1px">
                <tr>
                    <th>Manipulation</th>
                    <th>All tests passed with manipulation (BAD)</th>
                    <th></th>
                </tr>`

	for _, v := range PATHS {
		tableHTML += fmt.Sprintf(`<tr>
                    <td>%s</td>
                    <td align="center">%s of %s</td>
                    <td><a href='/compare?GOPATH=%s&PACKAGENAME=%s&CURRENTFILE=%s'>View</a></td>
                </tr>`, (*v).Name, (*v).FalsePos, (*v).Iterations, (*v).GOPATH, PACKAGENAME, (*v).Name)
	}
	tableHTML += "</table>"

	return tableHTML
}

func fetchResults(args []string) {

	if len(args) < 1 {
		args = append(args, "0")
	}
	DEBUG = args[0]
}

func dojoHandler(w http.ResponseWriter, r *http.Request) {

	f1, err0 := os.Open("diffview/dojo.js")
	if err0 != nil {
		panic("File open error")
	}
	stat1, _ := f1.Stat()
	fout1 := make([]byte, stat1.Size())
	_, err0 = f1.Read(fout1)
	string1 := fmt.Sprintf("%s", fout1)
	fmt.Fprintf(w, string1)
}

func difflibHandler(w http.ResponseWriter, r *http.Request) {
	f1, err0 := os.Open("diffview/difflib.js")
	if err0 != nil {
		panic("File open error")
	}
	stat1, _ := f1.Stat()
	fout1 := make([]byte, stat1.Size())
	_, err0 = f1.Read(fout1)
	string1 := fmt.Sprintf("%s", fout1)
	fmt.Fprintf(w, string1)
}

func diffviewHandler(w http.ResponseWriter, r *http.Request) {
	f1, err0 := os.Open("diffview/diffview.js")
	if err0 != nil {
		panic("File open error")
	}
	stat1, _ := f1.Stat()
	fout1 := make([]byte, stat1.Size())
	_, err0 = f1.Read(fout1)
	string1 := fmt.Sprintf("%s", fout1)
	fmt.Fprintf(w, string1)
}

func diffcssHandler(w http.ResponseWriter, r *http.Request) {
	f1, err0 := os.Open("diffview/diffview.css")
	if err0 != nil {
		panic("File open error")
	}
	stat1, _ := f1.Stat()
	fout1 := make([]byte, stat1.Size())
	_, err0 = f1.Read(fout1)
	string1 := fmt.Sprintf("%s", fout1)
	fmt.Fprintf(w, string1)
}

var resultText = `
	<!DOCTYPE html>
	<html>
	    <head>
	        <title>%s</title>
	        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	    </head>
	    <body>
	    	<h1>Manipulation Results:</h1>
	    	<a href="/">All Results</a>

                %s
	    </body>
	</html>`

var compareText = `<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Online Code Difference Comparison Tool</title>
    <meta name="description" content="Online Code Difference Comparison Tool allows you to paste two pieces of code or text and view the changes between the two.">

    <script type="text/javascript" src="dojo.js"></script>
    <link rel="stylesheet" type="text/css" href="diffview.css">
    <script type="text/javascript" src="diffview.js"></script>
    <script type="text/javascript" src="difflib.js"></script>


    <script language="javascript">
                        var $=dojo.byId;dojo.require("dojo.io");var url=window.location.toString().split("#")[0];function diffUsingJS(){
                            var base=difflib.stringAsLines($("baseText").value);var newtxt=difflib.stringAsLines($("newText").value);var sm=new difflib.SequenceMatcher(base,newtxt);var opcodes=sm.get_opcodes();var diffoutputdiv=$("diffoutput");while(diffoutputdiv.firstChild)diffoutputdiv.removeChild(diffoutputdiv.firstChild);var contextSize=$("contextSize").value;contextSize=contextSize?contextSize:null;diffoutputdiv.appendChild(diffview.buildView({baseTextLines:base,newTextLines:newtxt,opcodes:opcodes,baseTextName:"Base Text",newTextName:"New Text",contextSize:contextSize,viewType:1}));window.location=url+"#diff";}function diffUsingPython(){dojo.io.bind({url:"/diff/postYieldDiffData",method:"POST",content:{baseText:$("baseText").value,newText:$("newText").value,ignoreWhitespace:"Y"},load:function(type,data,evt){try{data=eval('('+data+')');while(diffoutputdiv.firstChild)diffoutputdiv.removeChild(diffoutputdiv.firstChild);$("output").appendChild(diffview.buildView({baseTextLines:data.baseTextLines,newTextLines:data.newTextLines,opcodes:data.opcodes,baseTextName:data.baseTextName,newTextName:data.newTextName,contextSize:contextSize}));}catch(ex){alert("An error occurred updating the diff view:\n"+ex.toString());}},error:function(type,evt){alert('Error occurred getting diff data.  Check the server logs.');},type:'text/javascript'});}
    </script>
    </head>
      
    
	<body onload="diffUsingJS()">

		<h1>%s</h1>
	    <a href="/">Home</a>
	    <h2>Cmd Args:<br>%s<br>%s<br>%s</h2>

        <FORM NAME ="form1" METHOD ="GET" ACTION = "/compare">
           %s
    	<input type="text" value="%s" name="GOPATH" style="visibility: hidden">
    	<input type="text" value="%s" name="PACKAGENAME" style="visibility: hidden">
    	<input type="text" value="%s" name="CURRENTFILE" style="visibility: hidden">
        </FORM>

        <h1>Code Difference Comparison Tool</h1>

        <input id="contextSize" type="text" style="visibility: hidden">

        <textarea id="baseText" style="visibility: hidden">
            %s
        </textarea>
        <textarea id="newText" style="visibility: hidden">
            %s
        </textarea>

        <a name="diff"> </a>
        <div id="diffoutput" style="width:100%%"> </div>


</body>
</html>`
